package com.pyb.common.datasource.aspectj;

import com.pyb.common.datasource.DynamicDataSource;
import com.pyb.common.datasource.enums.DataSourceEnum;
import com.pyb.common.exception.BizException;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * DaoMethodAop
 *
 * @author chuchen.zhang
 * @date 17-2-27 下午4:05
 */
@Component
@Aspect
@Order(1)
public class DaoMethodAop {

	private static final Logger logger = LoggerFactory.getLogger(DaoMethodAop.class);

	private static final String PACKAGE_DAO_PATTERN = "com\\.pyb\\.(\\p{Alpha}*)\\.dao.\\p{Alpha}+Dao";

	private static final Pattern packageDaoPattern = Pattern.compile(PACKAGE_DAO_PATTERN);

	/**
	 * 为所有insure包下dao包下的public方法设置insure的数据源
	 */
	@Around("execution(public * com.pyb..*Dao.*(..))")
	public Object changeDataSource(ProceedingJoinPoint pjp) throws Throwable {
		Exception errorException = null;
		try {
			String pointStr = pjp.toString();
			Matcher matcher = packageDaoPattern.matcher(pointStr);
			if (matcher.find()) {
				DataSourceEnum dataSourceEnum = DataSourceEnum.match(matcher.group(1));
				if (dataSourceEnum == null) {
					throw new BizException("cant match datasource, aop name : " + pointStr);
				}
				DynamicDataSource.contextHolder.set(dataSourceEnum.getText());
				logger.debug("change datasource to {}", dataSourceEnum.getText());
				return pjp.proceed();
			} else {
				throw new BizException("cant match datasource, aop name : " + pointStr);
			}
		} catch (Exception e) {
			errorException = e;
		} finally {
			DynamicDataSource.contextHolder.remove();
		}
		if ((errorException != null) && (errorException instanceof BizException)) {
			throw errorException;
		}
		if (errorException != null)	{
			String errorMsg = "change datasource error";
			logger.error(errorMsg, errorException);
			throw new BizException(errorException, errorMsg);
		}
		return null;
	}

}
